#include <bits/stdc++.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
using namespace std;
void sighandler(int a)
{
  cout << "process get a signal:" << a << endl;
  // execl("/usr/bin/ls","ls","-l","-a",nullptr);
  // exit(0);
  //  alarm(5);
  int n = alarm(5);
  cout << "剩余时间: " << n << endl;
}
// int main()
// {
//  //signal(2,sighandler);//只需要设置一次,往后都有效
//  signal(3,sighandler);//ctrl \ 3号信号
//  //信号的产生和我们自己的代码运行是异步的
//    while(true)
//    {
//     cout << "I am a process\n";
//     sleep(1);
//    }

//   return 0;
// }

// void Usage(const string& s)
// {
//   //\t指标符号
//   cout << "Usage: \n\t" << s  << "sigunm pid\n";

// }
// int main(int argc,char* argv[])
// {
//   //   if(argc != 3)
//   //   {
//   //     Usage(argv[0]);
//   //     exit(0);
//   //   }
//   // //int kill(pid_t pid,int sig)
//   // int sig = stoi(argv[1]);
//   // int pid = stoi(argv[1]);

//   // int ret = kill(pid,sig);
//   // if(ret == -1)
//   // {
//   //   perror("kill");
//   //   exit(0);
//   // }
//   int cnt = 5;
//   // signal(2,sighandler);
//   signal(SIGABRT,sighandler);

//   while(true)
//   {
//     cout << "I am a process,pid: " << getpid() << endl;
//     sleep(1);
//     cnt--;
//     if(cnt == 0)
//     {
//       abort();
//     }
//     //raise(2);
//   }
//   return 0;
// }

// int main()
// {
//   //8号信号
//   //signal(SIGFPE,sighandler);
//   //

//   //11号信号
//   signal(SIGSEGV,sighandler);
//   //cout << "div before" << endl;
//   cout << "ptr before" << endl;

//   sleep(1);
//  //int a = 10;
//  //为什么信号一直被触发?
//  //a /= 0;
//  int *p = nullptr;
//  *p = 100;
//   // cout << "div after" << endl;
//   cout << "ptr after" << endl;

//   return 0;
// }
// void _sleep(int a)
// {
//    exit(0);
// }
// void Mysleep(int n)
// {
//   signal(SIGALRM,_sleep);
//   alarm(n);
// }

// int main()
// {
//    signal(SIGALRM,sighandler);
//  int n = alarm(1000000);
//  while(1)
//  {
//    cout << "proc is running,pid: " << getpid() << endl;
//    sleep(1);
//  }
//   return 0;
// }

// int main()
// {
//   pid_t id = fork();
//   if(id == 0)
//   {
//     //child
//     int cnt  = 500;
//     while(cnt --)
//     {
//       cout << "I am a child process,pid: " << getpid() << " cnt: " << cnt << endl;
//       sleep(1);
//     }
//   }
//   int status = 0;
//   pid_t rid = waitpid(id,&status,0);
//  if(rid == id)
//  {
//    cout << "rid: " << rid ;
//    cout << " " << "exit code "<< ((status>>8)&0xFF) << " exit signal " << (status&0x7f) << " ";
//    cout << " core dump " << ((status>>7)&1);
//  }

//   return 0;
// }

// int main()
// {
//   int a = 3;
//   int b = 0;

//   a /= b;
//   cout << "a:" << a << endl;
//   return 0;
// }
// void PrintPending(const sigset_t &sp)
// {
//   for(int i = 31;i >= 1;--i)
//   {
//   if(sigismember(&sp,i))
//   {
//       cout << "1" ;
//   }
//   else cout << "0";
//   }
// }
// void func(int c)
// {
//   cout << "catch a signo" << c << endl;
// }
// int main()
// {
//   // signal(2,SIG_IGN);

//   //  while(1)
//   //  {
//   //   cout << "hello signal" << endl;
//   //    sleep(1);
//   //  }

//   //1.对2号信号进行屏蔽
//   sigset_t s,olds;
//   sigemptyset(&s);
//   sigemptyset(&olds);
//   sigaddset(&s,2);//还没有屏蔽!
//   sigprocmask(SIG_SETMASK,&s,&olds);//屏蔽了,没收到
//   signal(2,func);
//   //2.重复打印当前进程的pending
//    //2.1发送2号 pending结构改变!
//   sigset_t sp;
//   int cnt = 10;
//   while(cnt --)
//   {
//     int n = sigpending(&sp);
//     if(n == 0)
//     {
//         PrintPending(sp);
//         cout << endl;
//         sleep(1);
//     }

//      sleep(1);
//      //解除阻塞
//      if(cnt == 3)
//      {
//       cout << "unblock 2 signo" << endl;
//     // sigprocmask(SIG_UNBLOCK,&s,&olds);
//        sigprocmask(SIG_SETMASK,&olds,nullptr);
//      }
//   }

//   return 0;
// }

//   //可以将所有的信号都屏蔽,信号不就不会被处理了吗?
//   //肯定不行,一定有一些信号不可被屏蔽的!
// 9和19不可以被屏蔽! !  !
// int main()
// {
//   sigset_t bset,oset;
//   sigemptyset(&bset);
//   sigemptyset(&oset);
//   for(int i = 1;i <= 31;++i)
//   {
//     sigaddset(&bset,i);
//   }
//   sigprocmask(SIG_SETMASK,&bset,&oset);
//   sigset_t sp;
//   while(1)
//   {
//     sigpending(&sp);
//     cout << "proc is running\n";
//     sleep(1);
//     PrintPending(sp);
//   }

//   return 0;
// }
// void PrintPending()
// {
//   sigset_t s;
//   sigpending(&s);
//   for(int i = 31;i >= 1;i--)
//   {
//     if(sigismember(&s,i))
//     {
//          cout << "1";
//     }
//     else cout << '0';
//   }
//   cout << '\n';
// }

// void handler(int a)
// {
//   cout << "catch a signal" << endl;
//   while(1)
//   {
//     PrintPending();
//     sleep(1);
//   }
// }
// int main()
// {
//   struct sigaction act,oldact;
//   memset(&act,0,sizeof(act));
//   memset(&oldact,0,sizeof(oldact));

//   act.sa_handler = handler;
//   sigemptyset(&act.sa_mask);
//   sigaddset(&act.sa_mask,1);
//   sigaddset(&act.sa_mask,4);
//   sigaddset(&act.sa_mask,3);

//   sigaction(2,&act,&oldact);
//   while(true)
//   {
//      cout << "I am a process: " << getpid() << endl;
//      sleep(1);
//   }

//   return 0;
// }

// volatile int flag = 0;//volatile关键字,防止编译器过度优化,保持内存的可见性
// 还可以用于const
// void handler(int signo)
// {
//   cout << "catch a signal" << endl;
//   flag = 1;
// }
// int main()
// {
//   signal(2,handler);

//   //在优化条件下,flag变量可能被直接优化到CPU内部的寄存器里
//   //-O0没有优化的条件下会Ctrl + C会结束进程，-O1的情况下就不会结束,优化了
//   //优化的情况下flag为什么没被改变呢? ? ?
//   //优化之后每次都在CPU内部直接读取,内存中的flag改了没有影响 !!!

//   while(!flag);

//   cout << "Process quit" << endl;
//   return 0;
// }

//一定得调用wait么 ? ? > 必须得等吗
//17->SIG_IGN
void handler(int a)
{
  sleep(5);
  pid_t rid;
  while ((rid = waitpid(-1, nullptr, WNOHANG) > 0))
    cout << "I am a process: " << getpid() << " catch a signo: " << a
         << " child process quit: " << rid << endl;
}
int main()
{
  srand(time(0));
  // signal(17, handler);
  signal(17,SIG_IGN); //SIG_DFL -> action -> IGN
  // 如果有10个子进程呢? while 循环 + 非阻塞
  // 同时退出呢?
  // 如果退出一半呢?
  for (int i = 0; i < 10; ++i)
  {
    pid_t id = fork();
    if (id == 0)
    {
      while (true)
      {
        cout << "I am child process: " << getpid() << " ppid: " << getppid() << '\n';
        sleep(10);
        break;
      }
      cout << "child quit " << endl;
      exit(0);
    }
    // sleep(rand() % 5 + 3);
    sleep(1);

  }
  while (true)
  {
    cout << "I am father process: " << getpid() << endl;
    sleep(1);
  }
}